import type { AxiosRequestConfig } from "axios"
import http from "../http"
import { stringfyConfig } from "../axiosCancel"
// 并发调度器
class Scheduler {
	count: number
	threshold: number
	requests: AxiosRequestConfig[]
	results: any[]
	constructor() {
		this.count = 0
		this.requests = []
		this.results = []
		this.threshold = navigator.userAgent.indexOf("Chrome") > -1 ? 6 : 8
	}

	isOver() {
		return this.count > this.threshold
	}

	callback<T>(result: T) {
		this.count -= 1
		if (this.requests.length > 0) {
			this.request(this.requests[0])?.then((res) => {
				const key = stringfyConfig(this.requests[0])
				let obj: any = {}
				obj[key] = res
				this.results.push(obj)
			})
			this.requests.splice(0, 1)
		}
		return result
	}

	getData(key: string) {
		return new Promise((resolve) => {
			const data = this.results.find((it) => Object.keys(it)[0] === key)
			if (data) {
				resolve(data)
			}
		})
	}

	add(config: AxiosRequestConfig) {
		this.requests.push(config)
		const key = stringfyConfig(config)
		return this.getData(key)
	}

	request(config: AxiosRequestConfig) {
		if (this.isOver()) return this.add(config)
		this.count += 1
		return http.request(config).then(this.callback)
	}

	get<T, K>(url: string, params?: K, _object = {}) {
		if (this.isOver()) return this.add({ url, params: { ...params, ..._object }, method: "GET" })
		this.count += 1
		return http.get<T, K>(url, params).then(this.callback)
	}
	post<T, K>(url: string, data?: K, _object = {}) {
		if (this.isOver()) return this.add({ url, data: { ...data, ..._object }, method: "POST" })
		this.count += 1
		return http.post<T, K>(url, data).then(this.callback)
	}
	put<T, K>(url: string, data?: K, _object = {}) {
		if (this.isOver()) return this.add({ url, data: { ...data, ..._object }, method: "PUT" })
		this.count += 1
		return http.put<T, K>(url, data).then(this.callback)
	}
	delete<T, K>(url: string, data?: K, _object = {}) {
		if (this.isOver()) return this.add({ url, data: { ...data, ..._object }, method: "DELETE" })
		this.count += 1
		return http.delete<T, K>(url, data).then(this.callback)
	}
}

const scheduler = new Scheduler()

export default scheduler
